/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2006，所有权利保留。
 * 
 * 文件名：	BUserMgr.java
 * 模块说明：	
 * 修改历史：
 * 2006-8-22 - lxm - 创建。
 */
package com.hd123.rumba.user.biz;

import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Transaction;

import com.hd123.rumba.domain.CDomain;
import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.domain.IDomainMgr;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.gwt.base.client.biz.BPersistent;
import com.hd123.rumba.runtime.IManager;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.runtime.OperateContext;
import com.hd123.rumba.runtime.biz.BManager;
import com.hd123.rumba.user.CRole;
import com.hd123.rumba.user.CUser;
import com.hd123.rumba.user.IRole;
import com.hd123.rumba.user.IRoleMgr;
import com.hd123.rumba.user.IUser;
import com.hd123.rumba.user.IUserMgr;
import com.hd123.rumba.util.ClassifiedHashtable;

/**
 * 用户 | 业务层 | 管理员 | 实现类
 * 
 * @author lxm
 * 
 */
public class BUserMgr extends BManager implements IBUserMgr {

  public IManager getPerzMgr() throws BusinessException {
    return getUserMgr();
  }

  public BUser createUser(String domainUuid) throws BusinessException, HibernateException {
    checkParameterNotNull(domainUuid, "domainUuid");
    BUser buser = new BUser();
    IDomainMgr domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    IDomain domain = domainMgr.getValidDomain(domainUuid);
    if (domain == null)
      throw new BusinessException("指定的" + CDomain.CAPTION_CLASS + "\"" + domainUuid
          + "\"找不到，或者不可用。");
    IUser puser = getUserMgr().createUser(domain);
    buser.readFrom(puser);
    return buser;
  }

  public BUser loadUser(String uuid) throws BusinessException, HibernateException {
    checkParameterNotNull(uuid, "uuid");
    IUser puser = getUserMgr().getUser(uuid);
    if (puser != null) {
      BUser buser = new BUser();
      buser.readFrom(puser);
      return buser;
    } else
      return null;
  }

  public List<SRole> loadUserRoles(String userUuid) throws BusinessException, HibernateException {
    checkParameterNotNull(userUuid, "userUuid");
    IUser puser = getUserMgr().getUser(userUuid);
    if (puser == null)
      return null;
    List plist = getUserMgr().createRolesList(puser);
    List<SRole> list = new ArrayList();
    for (int i = 0; i < plist.size(); i++) {
      IRole prole = (IRole) plist.get(i);
      SRole role = new SRole();
      role.readFrom(prole);
      list.add(role);
    }
    return list;
  }

  public ClassifiedHashtable saveUserT(BUser user, OperateContext operate)
      throws BusinessException, HibernateException {
    checkParameterNotNull(user, "user");
    checkParameterNotNull(operate, "operate");

    IDomainMgr dmMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    IDomain domain = dmMgr.getDomain(user.getDomain().getUuid());
    IUser puser = createOrLoadPUser(user, domain);
    ClassifiedHashtable h = verifyToSave(user, puser, domain);
    if (h != null)
      return h;
    writeTo(user, puser);

    Transaction tx = getSession().beginTransaction();
    try {
      getUserMgr().saveUser(puser, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
      // 重新取出role。
      user.readFrom(puser);
    }

    return null;
  }

  public ClassifiedHashtable saveUserRolesT(String userUuid, List<SRole> roles,
      OperateContext operate, long userOca) throws BusinessException, HibernateException {
    checkParameterNotNull(userUuid, "userUuid");
    checkParameterNotNull(roles, "roles");
    checkParameterNotNull(operate, "operate");

    IUser puser = getUserMgr().getUser(userUuid);
    ClassifiedHashtable h = verifyToSaveRoles(puser, userOca);
    if (h != null)
      return h;

    boolean isRootAdmin = false;
    if (puser.getDomain().getUuid().equals(getDomainMgr().getRootDomain().getUuid())
        && CUser.VALUE_LOGIN_ROOT_ADMIN.equalsIgnoreCase(puser.getLogin()))
      isRootAdmin = true;
    IRoleMgr roleMgr = (IRoleMgr) NamingMgr.getInstance().lookupMgr(IRoleMgr.class);

    Transaction tx = getSession().beginTransaction();
    try {

      // 删除角色
      List plist = getUserMgr().createRolesList(puser);
      for (int i = 0; i < plist.size(); i++) {
        IRole prole = (IRole) plist.get(i);
        // root域admin用户，始终拥有admin角色。
        if (isRootAdmin && CRole.VALUE_CODE_ROOT_ADMIN.equalsIgnoreCase(prole.getCode()))
          continue;
        boolean exists = false;
        for (int j = 0; j < roles.size(); j++)
          if (roles.get(j).getUuid().equals(prole.getUuid())) {
            exists = true;
            break;
          }
        if (!exists)
          getUserMgr().removeRoleFromUser(prole, puser, operate);
      }

      // 添加角色
      plist = getUserMgr().createRolesList(puser);
      for (int i = 0; i < roles.size(); i++) {
        SRole role = roles.get(i);
        boolean exists = false;
        for (int j = 0; j < plist.size(); j++) {
          IRole prole = (IRole) plist.get(j);
          if (role.getUuid().equals(prole.getUuid())) {
            exists = true;
            break;
          }
        }
        if (!exists) {
          IRole prole = roleMgr.getRole(role.getUuid());
          getUserMgr().assignRoleToUser(prole, puser, operate);
        }
      }

      getUserMgr().saveUser(puser, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }

    return null;
  }

  public void offlineUserT(String userUuid, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    checkParameterNotNull(userUuid, "userUuid");
    checkParameterNotNull(operate, "operate");

    IUser puser = getUserMgr().getUser(userUuid);
    if (puser == null)
      throw new BusinessException("找不到指定uuid(" + userUuid + ")的" + CUser.CAPTION_CLASS + "。");
    ClassifiedHashtable h = verifyToOffline(puser, operate, oca);
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    // 若已经被禁用则不作任何事。
    if (!puser.getOnline().booleanValue())
      return;
    Transaction tx = getSession().beginTransaction();
    try {
      puser.setOnline(Boolean.FALSE);
      getUserMgr().saveUser(puser, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
  }

  public void onlineUserT(String userUuid, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    checkParameterNotNull(userUuid, "userUuid");
    checkParameterNotNull(operate, "operate");

    IUser puser = getUserMgr().getUser(userUuid);
    if (puser == null)
      throw new BusinessException("找不到指定uuid(" + userUuid + ")的" + CUser.CAPTION_CLASS + "。");
    ClassifiedHashtable h = verifyToOnline(puser, operate, oca);
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    // 若已经被启用则不作任何事。
    if (puser.getOnline().booleanValue())
      return;
    Transaction tx = getSession().beginTransaction();
    try {
      puser.setOnline(Boolean.TRUE);
      getUserMgr().saveUser(puser, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
  }

  public void deleteUserT(String userUuid, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    checkParameterNotNull(userUuid, "userUuid");
    checkParameterNotNull(operate, "operate");

    IUser puser = getUserMgr().getUser(userUuid);
    if (puser == null)
      throw new BusinessException("找不到指定uuid(" + userUuid + ")的" + CUser.CAPTION_CLASS + "。");
    ClassifiedHashtable h = verifyToDelete(puser, operate, oca);
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    Transaction tx = getSession().beginTransaction();
    try {
      getUserMgr().deleteUser(puser, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
  }

  public void undeleteUserT(String userUuid, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    checkParameterNotNull(userUuid, "userUuid");
    checkParameterNotNull(operate, "operate");

    IUser puser = getUserMgr().getUser(userUuid);
    if (puser == null)
      throw new BusinessException("找不到指定uuid(" + userUuid + ")的" + CUser.CAPTION_CLASS + "。");
    ClassifiedHashtable h = verifyToUndelete(puser, operate, oca);
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    Transaction tx = getSession().beginTransaction();
    try {
      getUserMgr().undeleteUser(puser, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
  }

  public <T extends BPersistent> T getUser(String uuid, Class<T> bizClass)
      throws BusinessException, HibernateException {
    IUser perz = getUserMgr().getUser(uuid);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  public <T extends BPersistent> T getValidUser(String uuid, Class<T> bizClass)
      throws BusinessException, HibernateException {
    IUser perz = getUserMgr().getValidUser(uuid);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  public <T extends BPersistent> T getUserByLogin(String domainUuid, String login, Class<T> bizClass)
      throws BusinessException, HibernateException {
    checkParameterNotNull(domainUuid, "domainUuid");
    IDomainMgr domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    IDomain domain = domainMgr.getDomain(domainUuid);
    if (domain == null)
      throw new BusinessException("指定的" + CDomain.CAPTION_CLASS + "\"" + domainUuid + "\"找不到。");
    IUser perz = getUserMgr().getUserByLogin(domain, login);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  public List<BUser> getAllUsers(String domainUuid) throws BusinessException, HibernateException {
    checkParameterNotNull(domainUuid, "domainUuid");
    IDomainMgr domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    IDomain domain = domainMgr.getDomain(domainUuid);
    if (domain == null)
      throw new BusinessException("指定的" + CDomain.CAPTION_CLASS + "\"" + domainUuid + "\"找不到。");
    List plist = getUserMgr().createAllUsersList(domain);
    List<BUser> list = new ArrayList();
    for (int i = 0; i < plist.size(); i++) {
      IUser puser = (IUser) plist.get(i);
      if (!CUser.VALUE_STATE_DELETED.equals(puser.getState())) {
        BUser user = new BUser();
        user.readFrom(puser);
        list.add(user);
      }
    }
    return list;
  }

  public IBPermAgent createUserPermAgent(String userUuid) throws BusinessException {
    IBPermAgent agent = new BUserPermAgent();
    agent.setUserOrRoleUuid(userUuid);
    return agent;
  }

  public IBPermAgent createUserProjectivePermAgent(String userUuid) throws BusinessException {
    IBPermAgent agent = new BUserProjectivePermAgent();
    agent.setUserOrRoleUuid(userUuid);
    return agent;
  }

  private IUserMgr puserMgr = null;
  private IDomainMgr domainMgr = null;

  /**
   * 取得持久层的用户管理员。
   * 
   * @return
   * @throws BusinessException
   */
  private IUserMgr getUserMgr() throws BusinessException {
    if (puserMgr == null)
      puserMgr = (IUserMgr) NamingMgr.getInstance().lookupMgr(IUserMgr.class);
    return puserMgr;
  }

  private IDomainMgr getDomainMgr() throws BusinessException {
    if (domainMgr == null)
      domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    return domainMgr;
  }

  private ClassifiedHashtable verifyToSave(BUser user, IUser puser, IDomain domain)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = this.checkOca(puser, user.getOca(), CUser.CAPTION_CLASS, puser
        .getNameCode());
    if (h != null)
      return h;

    h = new ClassifiedHashtable();

    if (user.getLogin() == null)
      user.setLogin("");
    else
      user.setLogin(user.getLogin().trim());
    if ("".equals(user.getLogin()))
      h.putMessage("login", ClassifiedHashtable.ERROR, CUser.CAPTION_CLASS + "的"
          + CUser.CAPTION_LOGIN + "不能为空。");
    else {
      IUser puser2 = getUserMgr().getUserByLogin(domain, user.getLogin());
      if (puser2 != null && !puser2.getUuid().equals(user.getUuid()))
        h.putMessage("login", ClassifiedHashtable.ERROR, "已经存在相同" + CUser.CAPTION_LOGIN + "的"
            + CUser.CAPTION_CLASS + "。");
    }

    IDomain rootDomain = getDomainMgr().getRootDomain();
    if (puser.getDomain().getUuid().equals(rootDomain.getUuid())
        && CUser.VALUE_LOGIN_ROOT_ADMIN.equalsIgnoreCase(puser.getLogin())) {
      if (!CUser.VALUE_LOGIN_ROOT_ADMIN.equalsIgnoreCase(user.getLogin()))
        h.putMessage("login", ClassifiedHashtable.ERROR, "禁止修改" + CUser.CAPTION_CLASS + "\""
            + puser.getNameCode() + "@" + rootDomain.getNameCode() + "\"的" + CUser.CAPTION_LOGIN
            + "。");
    }

    if (user.getPassword() == null)
      user.setPassword("");
    if (user.getPasswordConfirm() == null)
      user.setPasswordConfirm("");
    if (!BUser.VALUE_PASSWORD_NOCHANGE.equals(user.getPassword())
        || !BUser.VALUE_PASSWORD_NOCHANGE.equals(user.getPasswordConfirm())) {
      if ("".equals(user.getPassword()) || "".equals(user.getPasswordConfirm()))
        h.putMessage("password", ClassifiedHashtable.ERROR, "输入的" + CUser.CAPTION_PASSWORD
            + "不可为空。");
      if (!user.getPassword().equals(user.getPasswordConfirm()))
        h.putMessage("password", ClassifiedHashtable.ERROR, "两次输入的" + CUser.CAPTION_PASSWORD
            + "必须相同。");
    }

    return h.size() > 0 ? h : null;
  }

  private void writeTo(BUser user, IUser puser) throws BusinessException {
    puser.setLogin(user.getLogin());
    puser.setName(user.getName());
    if (!BUser.VALUE_PASSWORD_NOCHANGE.equals(user.getPassword()))
      puser.encodePassword(user.getPassword());
    puser.setOnline(user.getOnline());
    puser.setValidFrom(user.getValidFrom());
    puser.setValidTo(user.getValidTo());
    puser.setRemark(user.getRemark());
    puser.setUseToken(user.getUseToken());
    puser.setTokenSn(user.getTokenSn());
    puser.setTokenPin(user.getTokenPin());
  }

  private ClassifiedHashtable verifyToDelete(IUser puser, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = checkOca(puser, oca, CUser.CAPTION_CLASS, puser.getNameCode());
    if (h != null)
      return h;

    h = new ClassifiedHashtable();
    if (puser.getUuid().equals(operate.getOperator().getUuid()))
      h.putMessage("user", ClassifiedHashtable.ERROR, "禁止删除当前登录的" + CUser.CAPTION_CLASS + "。");
    if (CUser.VALUE_STATE_DELETED.equals(puser.getState()))
      h.putMessage("state", ClassifiedHashtable.ERROR, "指定" + CUser.CAPTION_CLASS + " "
          + puser.getNameCode() + " 已经是 " + CUser.STATEMAP.get(puser.getState()) + " 状态，没有必要再删除。");

    IDomain rootDomain = getDomainMgr().getRootDomain();
    if (puser.getDomain().getUuid().equals(rootDomain.getUuid())
        && CUser.VALUE_LOGIN_ROOT_ADMIN.equalsIgnoreCase(puser.getLogin())) {
      h.putMessage("state", ClassifiedHashtable.ERROR, "禁止删除" + CUser.CAPTION_CLASS + "\""
          + puser.getNameCode() + "@" + rootDomain.getNameCode() + "\"。");
    }

    return h.size() > 0 ? h : null;
  }

  private ClassifiedHashtable verifyToUndelete(IUser puser, OperateContext operate, long oca)
      throws BusinessException {
    ClassifiedHashtable h = checkOca(puser, oca, CUser.CAPTION_CLASS, puser.getNameCode());
    if (h != null)
      return h;

    h = new ClassifiedHashtable();
    if (!CUser.VALUE_STATE_DELETED.equals(puser.getState()))
      h.putMessage("state", ClassifiedHashtable.ERROR, "指定" + CUser.CAPTION_CLASS + " "
          + puser.getNameCode() + " 已经是 " + CUser.STATEMAP.get(puser.getState()) + " 状态，没有必要再删除。");

    return h.size() > 0 ? h : null;
  }

  private ClassifiedHashtable verifyToOffline(IUser puser, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = checkOca(puser, oca, CUser.CAPTION_CLASS, puser.getNameCode());
    if (h != null)
      return h;

    h = new ClassifiedHashtable();
    if (puser.getUuid().equals(operate.getOperator().getUuid()))
      h.putMessage("user", ClassifiedHashtable.ERROR, "禁止禁用当前登录的" + CUser.CAPTION_CLASS + "。");

    IDomain rootDomain = getDomainMgr().getRootDomain();
    if (puser.getDomain().getUuid().equals(rootDomain.getUuid())
        && CUser.VALUE_LOGIN_ROOT_ADMIN.equalsIgnoreCase(puser.getLogin())) {
      h.putMessage("state", ClassifiedHashtable.ERROR, "禁止禁用" + CUser.CAPTION_CLASS + "\""
          + puser.getNameCode() + "@" + rootDomain.getNameCode() + "\"。");
    }

    return h != null && h.size() > 0 ? h : null;
  }

  private ClassifiedHashtable verifyToOnline(IUser puser, OperateContext operate, long oca)
      throws BusinessException {
    ClassifiedHashtable h = checkOca(puser, oca, CUser.CAPTION_CLASS, puser.getNameCode());
    return h != null && h.size() > 0 ? h : null;
  }

  private IUser createOrLoadPUser(BUser user, IDomain domain) throws BusinessException,
      HibernateException {
    IUser puser = null;
    if (user.getUuid() == null)
      puser = getUserMgr().createUser(domain);
    else
      puser = getUserMgr().getUser(user.getUuid());
    return puser;
  }

  private ClassifiedHashtable verifyToSaveRoles(IUser puser, long userOca)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = checkOca(puser, userOca, CUser.CAPTION_CLASS, puser.getNameCode());
    if (h != null)
      return h;

    h = new ClassifiedHashtable();
    if (CUser.VALUE_STATE_DELETED.equals(puser.getState()))
      h.putMessage("state", ClassifiedHashtable.ERROR, "禁止修改" + CUser.CAPTION_STATE + "为 "
          + CUser.STATEMAP.get(puser.getState()) + " 的" + CUser.CAPTION_CLASS + "所"
          + CUser.CAPTION_ROLES + "。");

    return h != null && h.size() > 0 ? h : null;
  }

}
